package com.driver.core.mapper.generator;

import com.driver.core.Column;
import com.driver.core.DBManager;
import com.driver.core.StringUtil;
import com.driver.core.Table;
import com.driver.core.mapper.annotation.Order;

import java.util.List;

public class SqlXMLGenerator extends AbstractXMLGenerator {

    public SqlXMLGenerator(Table table) {
        super(table);
    }

    public SqlXMLGenerator() {
    }

    @Override
    @Order(order = 10)
    public String selectCount() {
        StringBuilder sb = new StringBuilder();
        sb.append("\t<select id=\"selectCount\" resultType=\"java.lang.Integer\" parameterType=\"").append(config.getPackagePreffix()).append(".").append(config.getEntityPackageName()).append(".").append(table.getClassName()).append("\">\n");
        sb.append("\t\tSELECT count(*) FROM ").append(table.getTableName()).append("\n");
        sb.append("\t\t<include refid=\"Where_Condition\"/>\n");
        sb.append("\t</select>\n\n");
        return sb.toString();
    }

    @Override
    @Order(order = 20)
    public String selectById() {


        StringBuilder sb = new StringBuilder();
        sb.append("\t<select id=\"selectBy").append(StringUtil.upperFirstName(keyProperty)).append("\" resultMap=\"BaseResultMap\" parameterType=\"map\">\n");
        sb.append("\t\tSELECT \n\t\t<include refid=\"Column_List\"/> \n\t\tFROM \n\t\t").append(table.getTableName()).append("\n");
        sb.append("\t\tWHERE \n\t\t").append(keyColumn).append(" = #{").append(keyProperty).append("}\n");
        sb.append("\t</select>\n\n");
        return sb.toString();
    }


    @Override
    @Order(order = 30)
    public String selectOne() {
        StringBuilder sb = new StringBuilder();
        sb.append("\t<select id=\"selectOne\" resultMap=\"BaseResultMap\" parameterType=\"").append(config.getPackagePreffix()).append(".").append(config.getEntityPackageName()).append(".").append(table.getClassName()).append("\">\n");
        sb.append("\t\tSELECT ");
        if (DBManager.getConfig().getUrl().contains("sqlserver")) {
            sb.append("TOP 1");
        }
        sb.append(" \n\t\t<include refid=\"Column_List\"/> \n\t\tFROM \n\t\t").append(table.getTableName()).append("\n");
        sb.append("\t\t<include refid=\"Where_Condition\"/>\n");
        sb.append("\t\tORDER BY ").append(keyColumn).append(" DESC\n");
        if (DBManager.getConfig().getUrl().contains("mysql")) {
            sb.append("\t\tLimit 1\n");
        }
        sb.append("\t</select>\n\n");
        return sb.toString();
    }


    @Override
    @Order(order = 40)
    public String selectColumnNameByOne() {
        StringBuilder sb = new StringBuilder();
        sb.append("\n\t<select id=\"selectColumnNameByOne\" resultMap=\"BaseResultMap\" parameterType=\"").append("map").append("\" >\n");
        sb.append("\t\tSELECT ");

        if (DBManager.getConfig().getUrl().contains("sqlserver")) {
            sb.append("TOP 1 ");
        }
        sb.append("\n\t\t<choose>");
        sb.append("\n\t\t   <when test=\"columnName != null and columnName !='' \">");
        sb.append("\n\t\t       ${columnName}");
        sb.append("\n\t\t   </when>");
        sb.append("\n\t\t   <otherwise>");
        sb.append("\n\t\t        <include refid=\"Column_List\"/>");
        sb.append("\n\t\t   </otherwise>");
        sb.append("\n\t\t</choose>");
        sb.append("\n\t\tFROM \n\t\t").append(table.getTableName()).append("\n");
        sb.append("\t\t<include refid=\"Where_Column_Name_Condition\"/>\n");
        sb.append("\t\tORDER BY ").append(keyColumn).append(" DESC\n");
        if (DBManager.getConfig().getUrl().contains("mysql")) {
            sb.append("\t\tLimit 1\n");
        }
        sb.append("\t</select>\n\n");
        return sb.toString();
    }


    @Override
    @Order(order = 50)
    public String selectByList() {
        StringBuilder sb = new StringBuilder();
        sb.append("\t<select id=\"selectByList\" resultMap=\"BaseResultMap\" parameterType=\"").append(config.getPackagePreffix()).append(".").append(config.getEntityPackageName()).append(".").append(table.getClassName()).append("\">\n");
        sb.append("\t\tSELECT \n\t\t<include refid=\"Column_List\"/> \n\t\tFROM \n\t\t").append(table.getTableName()).append("\n");
        sb.append("\t\t<include refid=\"Where_Condition\"/>\n");
        sb.append("\t</select>\n\n");
        return sb.toString();
    }

    @Override
    @Order(order = 60)
    public String selectColumnNameByList() {
        StringBuilder sb = new StringBuilder();
        sb.append("\n\t<select id=\"selectColumnNameByList\" resultMap=\"BaseResultMap\" parameterType=\"").append("map").append("\" >\n");
        sb.append("\t\tSELECT");
        sb.append("\n\t\t<choose>");
        sb.append("\n\t\t   <when test=\"columnName != null and columnName !='' \">");
        sb.append("\n\t\t       ${columnName}");
        sb.append("\n\t\t   </when>");
        sb.append("\n\t\t   <otherwise>");
        sb.append("\n\t\t        <include refid=\"Column_List\"/>");
        sb.append("\n\t\t   </otherwise>");
        sb.append("\n\t\t</choose>");
        sb.append("\n\t\tFROM \n\t\t").append(table.getTableName()).append("\n");
        sb.append("\t\t<include refid=\"Where_Column_Name_Condition\"/>\n");
        sb.append("\t</select>\n\n");
        return sb.toString();
    }


    @Override
    @Order(order = 70)
    public String selectByMaps() {
        StringBuilder sb = new StringBuilder();
        sb.append("\t<select id=\"selectByMaps\" resultType=\"java.util.Map\" parameterType=\"").append(config.getPackagePreffix()).append(".").append(config.getEntityPackageName()).append(".").append(table.getClassName()).append("\">\n");
        sb.append("\t\tSELECT \n\t\t<include refid=\"Column_List\"/> \n\t\tFROM \n\t\t").append(table.getTableName()).append("\n");
        sb.append("\t\t<include refid=\"Where_Condition\"/>\n");
        sb.append("\t</select>\n\n");
        return sb.toString();
    }

    @Override
    @Order(order = 80)
    public String selectColumnNameByMaps() {
        StringBuilder sb = new StringBuilder();
        sb.append("\n\t<select id=\"selectColumnNameByMaps\" resultType=\"java.util.Map\" parameterType=\"").append("map").append("\" >\n");
        sb.append("\t\tSELECT");
        sb.append("\n\t\t<choose>");
        sb.append("\n\t\t   <when test=\"columnName != null and columnName !='' \">");
        sb.append("\n\t\t       ${columnName}");
        sb.append("\n\t\t   </when>");
        sb.append("\n\t\t   <otherwise>");
        sb.append("\n\t\t        <include refid=\"Column_List\"/>");
        sb.append("\n\t\t   </otherwise>");
        sb.append("\n\t\t</choose>");
        sb.append("\n\t\tFROM \n\t\t").append(table.getTableName()).append("\n");
        sb.append("\t\t<include refid=\"Where_Column_Name_Condition\"/>\n");
        sb.append("\t</select>\n\n");
        return sb.toString();
    }


    @Override
    @Order(order = 90)
    public String insert() {

        StringBuilder sb = new StringBuilder();
        sb.append("\t<insert id=\"insert\" useGeneratedKeys=\"true\" keyColumn=\"").append(keyColumn).append("\" keyProperty=\"").append(keyProperty).append("\" parameterType=\"").append(config.getPackagePreffix()).append(".").append(config.getEntityPackageName()).append(".").append(table.getClassName()).append("\">\n");
        sb.append("\t\tINSERT INTO ").append(table.getTableName()).append("\n");
        sb.append("\t\t<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");

        for (Column column : columns) {
            sb.append("\t\t\t<if test='null != ").append(column.getPropertyName()).append("'>\n");
            sb.append("\t\t\t\t").append(column.getColumnName()).append(",\n");
            sb.append("\t\t\t</if>\n");
        }
        sb.append("\t\t</trim>\n");

        sb.append("\t\t<trim prefix=\"VALUES (\" suffix=\")\" suffixOverrides=\",\">\n");

        for (Column column : columns) {
            sb.append("\t\t\t<if test='null != ").append(column.getPropertyName()).append("'>\n");
            sb.append("\t\t\t\t").append("#{").append(column.getPropertyName()).append("}").append(",\n");
            sb.append("\t\t\t</if>\n");
        }
        sb.append("\t\t</trim>\n");

        sb.append("\t</insert>\n\n");
        return sb.toString();
    }

    @Override
    @Order(order = 100)
    public String insertAllColumn() {

        StringBuilder sb = new StringBuilder();
        sb.append("\t<insert id=\"insertAllColumn\" useGeneratedKeys=\"true\" keyColumn=\"").append(keyColumn).append("\" keyProperty=\"").append(keyProperty).append("\" parameterType=\"").append(config.getPackagePreffix()).append(".").append(config.getEntityPackageName()).append(".").append(table.getClassName()).append("\">\n");
        sb.append("\t\tINSERT INTO \n\t\t").append(table.getTableName()).append(" (");
        for (Column column : columns) {
            if (!column.isPrivateKey()) {
                sb.append(column.getColumnName()).append(",");
            }
        }
        sb.setCharAt(sb.length() - 1, ' ');
        sb.append(")\n\t\t");
        sb.append("VALUES\n\t\t(");
        for (Column column : columns) {
            if (!column.isPrivateKey()) {
                sb.append("#{").append(column.getPropertyName()).append("},");
            }
        }
        sb.setCharAt(sb.length() - 1, ' ');
        sb.append(")\n\t</insert>\n\n");
        return sb.toString();
    }

    @Override
    @Order(order = 110)
    public String updateAllColumn() {
        List<Column> columns = table.getColumns();

        StringBuilder sb = new StringBuilder();
        sb.append("\t<update id=\"updateAllColumn").append("\" parameterType=\"map\">\n");
        sb.append("\t\tUPDATE ").append(table.getTableName()).append("\n");
        sb.append("\t\tSET\n");
        for (Column column : columns) {
            if (!column.isPrivateKey()) {
                sb.append("\t\t\t").append(column.getColumnName()).append(" = #{").append(StringUtil.lowerFirstName(table.getClassName())).append(".").append(column.getPropertyName()).append("},\n");
            }
        }
        sb.setCharAt(sb.length() - 2, ' ');
        sb.append("\t\t<include refid=\"Update_Where_Condition\"/>\n");
        sb.append("\t</update>\n\n");
        return sb.toString();
    }

    @Override
    @Order(order = 120)
    public String update() {
        List<Column> columns = table.getColumns();
        StringBuilder sb = new StringBuilder();
        sb.append("\t<update id=\"update\" parameterType=\"map\">\n");
        sb.append("\t\tUPDATE ").append(table.getTableName()).append("\n");
        sb.append("\t\t<set>\n");
        for (Column column : columns) {
            sb.append("\t\t\t<if test='null != ").append(StringUtil.lowerFirstName(table.getClassName())).append(".").append(column.getPropertyName()).append("'>\n");
            sb.append("\t\t\t\t").append(column.getColumnName()).append(" = #{").append(StringUtil.lowerFirstName(table.getClassName())).append(".").append(column.getPropertyName()).append("},\n");
            sb.append("\t\t\t</if>\n");
        }
        sb.append("\t\t</set>\n");
        sb.append("\t\t<include refid=\"Update_Where_Condition\"/>\n");
        sb.append("\t</update>\n\n");
        return sb.toString();
    }

    @Override
    @Order(order = 130)
    public String updateById() {

        StringBuilder sb = new StringBuilder();
        sb.append("\t<update id=\"updateBy").append(StringUtil.upperFirstName(keyProperty)).append("\" parameterType=\"map\">\n");
        sb.append("\t\tUPDATE ").append(table.getTableName()).append("\n");
        sb.append("\t\t<set>\n");
        for (Column column : columns) {
            if (!column.isPrivateKey()) {
                sb.append("\t\t\t<if test='null != ").append(StringUtil.lowerFirstName(table.getClassName())).append(".").append(column.getPropertyName()).append("'>\n");
                sb.append("\t\t\t\t").append(column.getColumnName()).append(" = #{").append(StringUtil.lowerFirstName(table.getClassName())).append(".").append(column.getPropertyName()).append("},\n");
                sb.append("\t\t\t</if>\n");
            }
        }
        sb.append("\t\t</set>\n");
        sb.append("\t\tWHERE ").append(keyColumn).append(" = #{").append(keyProperty).append("}\n");
        sb.append("\t</update>\n\n");
        return sb.toString();
    }

    @Override
    @Order(order = 140)
    public String deleteById() {


        StringBuilder sb = new StringBuilder();
        sb.append("\t<delete id=\"deleteBy").append(StringUtil.upperFirstName(keyProperty)).append("\" parameterType=\"map\">\n");
        sb.append("\t\tDELETE FROM ").append(table.getTableName()).append(" WHERE ").append(keyColumn).append("").append(" = #{").append(keyProperty).append("}\n");
        sb.append("\t</delete>\n\n");
        return sb.toString();
    }

    @Override
    @Order(order = 150)
    public String delete() {
        StringBuilder sb = new StringBuilder();
        sb.append("\t<delete id=\"delete\" parameterType=\"").append(config.getPackagePreffix()).append(".").append(config.getEntityPackageName()).append(".").append(table.getClassName()).append("\">\n");
        sb.append("\t\tDELETE FROM ").append(table.getTableName());
        sb.append("\n\t\t<include refid=\"Where_Condition\"/>\n");
        sb.append("\t</delete>\n\n");
        return sb.toString();
    }

    @Override
    @Order(order = 160)
    public String selectBySql() {
        StringBuilder sb = new StringBuilder();
        sb.append("\n\t<select id=\"selectBySql\" resultType=\"java.util.Map\" parameterType=\"").append("map").append("\" >\n");
        sb.append("\t\t${sql}");
        sb.append("\n\t</select>\n\n");
        return sb.toString();
    }
}
